package com.ybkj.daijia.api.driver.v1;

import com.ybkj.daijia.Setting;
import com.ybkj.daijia.api.driver.DeviceInfoData;
import com.ybkj.daijia.api.driver.ErrorConstant;
import com.ybkj.daijia.api.driver.SecurityUtils;
import com.ybkj.daijia.api.driver.transport.ResultTransport;
import com.ybkj.daijia.server.event.model.DriverOfflineEvent;
import com.ybkj.daijia.server.event.model.DriverOnlineEvent;
import com.ybkj.daijia.server.model.Company;
import com.ybkj.daijia.server.model.Driver;
import com.ybkj.daijia.server.service.CompanyService;
import com.ybkj.daijia.server.service.DriverService;
import com.ybkj.daijia.server.service.DriverTimeService;
import com.ybkj.daijia.server.service.ErrandService;
import com.ybkj.daijia.server.service.OrderService;
import com.ybkj.daijia.server.service.ZhuancheService;
import com.ybkj.daijia.server.websocket.WebSocketSend;
import com.ybkj.daijia.serverUtils.SettingUtils;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.crypto.hash.Sha256Hash;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.event.ApplicationEventMulticaster;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

/**
 * 司机登录相关
 *
 * @author bo
 */
//@Controller
@RequestMapping(value = "driver/api/rest/v1")
public class DriverAccountController {

    private static final Logger logger = LoggerFactory.getLogger(DriverAccountController.class);

    @Autowired
    private DriverService driverService;
    @Autowired
    private DriverTimeService driverTimeService;
    @Autowired
    private OrderService orderService;
    @Autowired
    private CompanyService companyService;
    @Autowired
    private ZhuancheService zhuancheService;
    @Autowired
    private ErrandService errandService;
    @Autowired
    private SettingUtils settingUtils;
    @Autowired
    private ApplicationEventMulticaster applicationEventMulticaster;

    /**
     * 修改司机密码
     *
     * @param id
     * @param oldPass
     * @param newPass
     * @param appKey
     * @param token
     * @param timestamp
     * @return
     */
    @RequestMapping(value = "modifyPass", method = RequestMethod.POST)
    public @ResponseBody
    ResultTransport modifyPass(Long id, String oldPass, String newPass, String appKey, String token,
        String timestamp) {

        logger
            .debug("recv id:{},oldPass:{},newPass:{},appKey:{},token:{},timestamp:{}", id, oldPass,
                newPass, appKey, token, timestamp);

        if (null == id || StringUtils.isBlank(newPass) || StringUtils.isBlank(newPass)
            || SecurityUtils.isBlank(appKey, token, timestamp)) {
            return ResultTransport.getErrorBy(ErrorConstant.PARAM_ERROR);
        }

        if (!StringUtils.isNumeric(timestamp) || !SecurityUtils
            .checkTimestamp(Long.parseLong(timestamp))) {
            return ResultTransport.getErrorBy(ErrorConstant.TIMESTAMP_ERROR);
        }

        List<String> params = new LinkedList<String>();
        params.add(String.valueOf(id));
        params.add(oldPass);
        params.add(newPass);
        params.add(timestamp);
        params.add(appKey);

        if (!SecurityUtils.checkToken(params, token)) {
            return ResultTransport.getErrorBy(ErrorConstant.TOKEN_ERROR);
        }

        try {

            Driver driver = driverService.findOne(id);

            if (null == driver) {
                return ResultTransport.getErrorBy(ErrorConstant.DRIVER_NOT_EXISTS);
            }

            Sha256Hash sha256Hash = new Sha256Hash(oldPass);

            if (!sha256Hash.toBase64().equals(driver.getPassword())) {
                return ResultTransport.getErrorBy(ErrorConstant.PASS_NOT_CORRECT_ERROR);
            }

            if (newPass.length() < 4 || newPass.length() > 20 || !newPass
                .matches("^[^\\s&\"<>]+$")) {
                return ResultTransport.getErrorBy(ErrorConstant.PASS_FORMAT_ERROR);
            }

            sha256Hash = new Sha256Hash(newPass);
            driver.setPassword(sha256Hash.toBase64());
            driverService.updateByPassword(sha256Hash.toBase64(), driver.getId());

            return ResultTransport.getErrorBy(ErrorConstant.SUCCESS); //密码修改成功

        } catch (Exception e) {
            logger.error("api v1 driver modifyPass error: {}", e);
            return ResultTransport.getErrorBy(ErrorConstant.SERVER_ERROR);
        }


    }

    /**
     * 设置司机目前为上班状态
     *
     * @param id
     * @param appKey
     * @param token
     * @param timestamp
     * @return
     */
    @RequestMapping(value = "online", method = RequestMethod.POST)
    public @ResponseBody
    ResultTransport online(Long id, String appKey, String token, String timestamp) {

        logger.debug("recv id:{},appKey:{},token:{},timestamp:{}", id, appKey, token, timestamp);

        if (null == id || SecurityUtils.isBlank(appKey, token, timestamp)) {
            return ResultTransport.getErrorBy(ErrorConstant.PARAM_ERROR);
        }

        if (!StringUtils.isNumeric(timestamp) || !SecurityUtils
            .checkTimestamp(Long.parseLong(timestamp))) {
            return ResultTransport.getErrorBy(ErrorConstant.TIMESTAMP_ERROR);
        }

        List<String> params = new LinkedList<String>();
        params.add(String.valueOf(id));
        params.add(timestamp);
        params.add(appKey);

        if (!SecurityUtils.checkToken(params, token)) {
            return ResultTransport.getErrorBy(ErrorConstant.TOKEN_ERROR);
        }

        try {

            Driver driver = driverService.findOne(id);

            if (null == driver) {
                return ResultTransport.getErrorBy(ErrorConstant.DRIVER_NOT_EXISTS);
            }
            if (driver.getIsFreeze()) { //帐号被冻结
                return ResultTransport.getErrorBy(ErrorConstant.USER_IS_FREEZE_ERROR);
            }

            Setting setting = settingUtils.get();
            if (driver.getType().equals(Driver.DRIVER_TYPR_PARTTIME)
                && setting.getLowestWorkVirtual() != 0
                && driver.getVirtual().doubleValue() < setting.getLowestWorkVirtual()) {

                return ResultTransport.getErrorBy(ErrorConstant.LOWEST_WORK_VIRTUAL_ERROR);

            }

            driver.setStatus(Driver.DRIVER_ONLINE);
            driver.setDutyTime(new Date());
            driverService.online(driver);

            DriverOnlineEvent driverOnlineEvent = new DriverOnlineEvent(driver);
            applicationEventMulticaster.multicastEvent(driverOnlineEvent);

            driver.setCompany(companyService.findOne(driver.getCompanyId()));

            ResultTransport instance = ResultTransport.getErrorBy(ErrorConstant.SUCCESS); //上班成功
            instance.setData(driver);

            return instance;

        } catch (Exception e) {
            logger.error("api v1 driver online error: {}", e);
            return ResultTransport.getErrorBy(ErrorConstant.SERVER_ERROR);
        }
    }

    /**
     * 司机请求设置上班状态
     *
     * @param id
     * @param appKey
     * @param token
     * @param timestamp
     * @return
     */
    @RequestMapping(value = "onlined", method = RequestMethod.POST)
    public @ResponseBody
    ResultTransport onlined(Long id, String appKey, String token, String timestamp) {

        logger.debug("recv id:{},appKey:{},token:{},timestamp:{}", id, appKey, token, timestamp);

        if (null == id || SecurityUtils.isBlank(appKey, token, timestamp)) {
            return ResultTransport.getErrorBy(ErrorConstant.PARAM_ERROR);
        }

        if (!StringUtils.isNumeric(timestamp) || !SecurityUtils
            .checkTimestamp(Long.parseLong(timestamp))) {
            return ResultTransport.getErrorBy(ErrorConstant.TIMESTAMP_ERROR);
        }

        List<String> params = new LinkedList<String>();
        params.add(String.valueOf(id));
        params.add(timestamp);
        params.add(appKey);

        if (!SecurityUtils.checkToken(params, token)) {
            return ResultTransport.getErrorBy(ErrorConstant.TOKEN_ERROR);
        }

        try {

            Driver driver = driverService.findOne(id);

            if (null == driver) {
                return ResultTransport.getErrorBy(ErrorConstant.DRIVER_NOT_EXISTS);
            }
            if (driver.getIsFreeze()) { //帐号被冻结
                return ResultTransport.getErrorBy(ErrorConstant.USER_IS_FREEZE_ERROR);
            }

            Setting setting = settingUtils.get();
            if (driver.getType().equals(Driver.DRIVER_TYPR_PARTTIME)
                && setting.getLowestWorkVirtual() != 0
                && driver.getVirtual().doubleValue() < setting.getLowestWorkVirtual()) {

                return ResultTransport.getErrorBy(ErrorConstant.LOWEST_WORK_VIRTUAL_ERROR);
            }

            if (driver.getStatus() == Driver.DRIVER_OFFLINE) {
                driver.setStatus(Driver.DRIVER_ONLINE);
                driver.setDutyTime(new Date());

                driverService.online(driver);

                DriverOnlineEvent driverOnlineEvent = new DriverOnlineEvent(driver);
                applicationEventMulticaster.multicastEvent(driverOnlineEvent);
            }

            driver.setCompany(companyService.findOne(driver.getCompanyId()));

            ResultTransport instance = ResultTransport.getErrorBy(ErrorConstant.SUCCESS); //上班成功
            instance.setData(driver);

            return instance;

        } catch (Exception e) {
            logger.error("api v1 driver onlined error: {}", e);
            return ResultTransport.getErrorBy(ErrorConstant.SERVER_ERROR);
        }
    }

    /**
     * 设置司机目前为下线状态
     *
     * @param id
     * @param appKey
     * @param token
     * @param timestamp
     * @return
     */
    @RequestMapping(value = "offline", method = RequestMethod.POST)
    public @ResponseBody
    ResultTransport offline(Long id, String appKey, String token, String timestamp) {

        logger.debug("recv id:{},appKey:{},token:{},timestamp:{}", id, appKey, token, timestamp);

        if (null == id || SecurityUtils.isBlank(appKey, token, timestamp)) {
            return ResultTransport.getErrorBy(ErrorConstant.PARAM_ERROR);
        }

        if (!StringUtils.isNumeric(timestamp) || !SecurityUtils
            .checkTimestamp(Long.parseLong(timestamp))) {
            return ResultTransport.getErrorBy(ErrorConstant.TIMESTAMP_ERROR);
        }

        List<String> params = new LinkedList<String>();
        params.add(String.valueOf(id));
        params.add(timestamp);
        params.add(appKey);

        if (!SecurityUtils.checkToken(params, token)) {
            return ResultTransport.getErrorBy(ErrorConstant.TOKEN_ERROR);
        }

        try {

            Driver driver = driverService.findOne(id);

            if (null == driver) {
                return ResultTransport.getErrorBy(ErrorConstant.DRIVER_NOT_EXISTS);
            }

            try {
                Long daijiaAmount = orderService.countActivedOrdersByDriver(driver.getId());
                if (daijiaAmount > 0) {
                    return ResultTransport.getErrorBy(ErrorConstant.HAS_ACTIVED_DAIJIA_ORDER_ERROR);
                }

                Long zhuancheAmount = zhuancheService.countActivedOrdersByDriver(driver.getId());
                if (zhuancheAmount > 0) {
                    return ResultTransport
                        .getErrorBy(ErrorConstant.HAS_ACTIVED_ZHUANCHE_ORDER_ERROR);
                }

                Long paotuiAmount = errandService.countBusyAmount(driver.getId());
                if (paotuiAmount > 0) {
                    return ResultTransport.getErrorBy(ErrorConstant.HAS_ACTIVED_PAOTUI_ORDER_ERROR);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }

            driver.setStatus(Driver.DRIVER_OFFLINE);
            driverService.updateStatus(Driver.DRIVER_OFFLINE, driver.getId());

            DriverOfflineEvent offlineEvent = new DriverOfflineEvent(driver);
            applicationEventMulticaster.multicastEvent(offlineEvent);

            driver.setCompany(companyService.findOne(driver.getCompanyId()));

            ResultTransport instance = ResultTransport.getErrorBy(ErrorConstant.SUCCESS); //上班成功
            instance.setData(driver);

            return instance;

        } catch (Exception e) {
            logger.error("api v1 driver modifyPass error: {}", e);
            return ResultTransport.getErrorBy(ErrorConstant.SERVER_ERROR);
        }
    }

    /**
     * 获取司机
     *
     * @param id
     * @return
     */
    @RequestMapping(value = "getDriver", method = RequestMethod.POST)
    public @ResponseBody
    ResultTransport getDriver(Long driverId, String appKey, String token, String timestamp) {

        logger.debug("recv driverId:{},appKey:{},token:{},timestamp:{}", driverId, appKey, token,
            timestamp);

        if (null == driverId || SecurityUtils.isBlank(appKey, token, timestamp)) {
            return ResultTransport.getErrorBy(ErrorConstant.PARAM_ERROR);
        }

        if (!StringUtils.isNumeric(timestamp) || !SecurityUtils
            .checkTimestamp(Long.parseLong(timestamp))) {
            return ResultTransport.getErrorBy(ErrorConstant.TIMESTAMP_ERROR);
        }

        List<String> params = new LinkedList<String>();
        params.add(String.valueOf(driverId));
        params.add(timestamp);
        params.add(appKey);

        if (!SecurityUtils.checkToken(params, token)) {
            return ResultTransport.getErrorBy(ErrorConstant.TOKEN_ERROR);
        }

        try {

            Driver driver = driverService.findOne(driverId);

            if (null == driver) {
                return ResultTransport.getErrorBy(ErrorConstant.DRIVER_NOT_EXISTS);
            }

            driver.setCompany(companyService.findOne(driver.getCompanyId()));

            Setting setting = settingUtils.get();
            driver.setPayCash1(setting.getPayCash1());
            driver.setPayCash2(setting.getPayCash2());
            driver.setPayCash3(setting.getPayCash3());

            ResultTransport instance = ResultTransport.getErrorBy(ErrorConstant.SUCCESS);
            instance.setData(driver);

            return instance;

        } catch (Exception e) {
            logger.error("api v1 driver getDriver error: {}", e);
            return ResultTransport.getErrorBy(ErrorConstant.SERVER_ERROR);
        }
    }

    /**
     * 获取设备信息
     *
     * @param id
     * @return
     */
    @RequestMapping(value = "getDeviceInfo", method = RequestMethod.POST)
    public @ResponseBody
    ResultTransport getDeviceInfo(DeviceInfoData data) {
        try {

            ResultTransport instance = ResultTransport.getErrorBy(ErrorConstant.SUCCESS);

            Long driverId = data.getDriverId();
            Driver driver = driverService.findOne(driverId);
            if (null != driver) {
                //推送
                JSONObject jsonObject = new JSONObject();
                jsonObject.put("type", "deviceinfo");
                jsonObject.put("driverId", data.getDriverId());
                jsonObject.put("networkType", data.getNetworkType());
                jsonObject.put("mobileVersion", data.getMobileVersion());
                jsonObject.put("operatorName", data.getOperatorName());
                jsonObject.put("systemVersion", data.getSystemVersion());
                jsonObject.put("ip", data.getIp());
                jsonObject.put("gps", data.isGps());
                jsonObject.put("root", data.isRoot());
                jsonObject.put("runningBackground", data.isRunningBackground());
                jsonObject.put("wifi", data.isWifi());
                Company mainCompany = companyService.getMain();
                Company driverCompany = companyService.findOne(driver.getCompanyId());
                WebSocketSend
                    .boardcastToCompany(jsonObject, driverCompany.getId(), mainCompany.getId());
            }

            return instance;

        } catch (Exception e) {
            logger.error("api v1 driver getDeviceInfo error: {}", e);
            return ResultTransport.getErrorBy(ErrorConstant.SERVER_ERROR);
        }
    }

    /**
     * 获取配置
     *
     * @param id
     * @return
     */
    @RequestMapping(value = "getSettings", method = RequestMethod.POST)
    public @ResponseBody
    ResultTransport getSettings() {
        try {

            ResultTransport instance = ResultTransport.getErrorBy(ErrorConstant.SUCCESS);
            instance.setData(getSettingMap());

            return instance;

        } catch (Exception e) {
            logger.error("api v1 driver getDriver error: {}", e);
            return ResultTransport.getErrorBy(ErrorConstant.SERVER_ERROR);
        }
    }

    /**
     * 获取配置map
     */
    public Map<String, Object> getSettingMap() {

        Map<String, Object> map = new HashMap<String, Object>();

        Setting setting = settingUtils.get();

        map.put("allowRushOrder", setting.isAllowRushOrder());
        map.put("allowWorkCar", setting.isAllowWorkCar());
        map.put("allowWorkCarZhuandan", setting.isAllowWorkCarZhuandan());
        map.put("allowDriverZhuandan", setting.isAllowDriverZhuandan());
        map.put("allowDriverCancel", setting.isAllowDriverCancel());
        map.put("mustToPlace", setting.isMustToPlace());
        map.put("mustMemberInfo", setting.isMustMemberInfo());
        map.put("errandFixPrice", setting.isPaotuiFixPrice());

        return map;

    }

}
